/*
Taylor Seale, Justin Bartlett, Ka Hin Lee
December 5, 2013
Project 4 - P2P Client

Client has 2 threads
	-The main thread which handles user interaction
	-A background tread handling connection requests from other clients
		-This thread spawns more threads to handle the requests
*/

#include <dirent.h>
#include <iostream>
#include <vector>
#include <string>
#include <stdio.h>		//for perror
#include <netinet/in.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <errno.h>
#include <stdlib.h>
#include <cstring>
#include <ifaddrs.h>	//to get ip address

#include <algorithm>	//for copy
#include <iterator>		//for ostream_iterator

#include <netdb.h> 		//so that the hostname as well as ip address can be passed

#include <string.h> //for memcpy

#include <pthread.h>

#define PORT 9976

//TODO - what errors to exit on
//TODO - htons ntohs consistency

using namespace std;

//typedefs
typedef pair <string, int> client_info;

//globals
char* self_ip_address;
vector<client_info> client_list;

//Forward declarations
char *get_ip_address(void);
string findFirstWord(string word);
string findSecondWord(string word);
string findThirdWord(string word);
string findFourthWord(string word);
string hostname_to_ip(char * hostname);
void checkInput(int argc);
vector<char *> searchDirectory(void);
vector<string> find_wildcard_matches(string filename);
void print_client_list(void);
int check_for_file(string filename, string ip_address, int port);
void get_file(string filename, string ip_address, int port);
void printWelcome(void);


// thread functions - connection handler spawns handle request 
void* handle_connection(void* param);
void* handle_request(void* param);


int main(int argc, char**argv)
{
   //initialize variables
   int sock;
   struct sockaddr_in servaddr;
   
   //check to see if passed arguments correctly
   checkInput(argc);

   //prevent freeloaderss
   vector<char *> client_data = searchDirectory();
   if (client_data.size()==0){
   	cout << "Cannot join network with 0 files to share!\nAdd some files to your 'files' directory to join\n";
   	exit(1);
   }
   
   //create socket
   sock = socket(AF_INET, SOCK_STREAM, 0);
   if (sock < 0)
   {
	  cout << "Error: Failure creating socket" << endl;
	  exit(1);
   }
   
   //convert hostname to ip address if necessary
   string ipAddress;
   ipAddress = hostname_to_ip(argv[1]);
   
   //initialize server info
   bzero(&servaddr,sizeof(servaddr));
   servaddr.sin_family = AF_INET;
   servaddr.sin_addr.s_addr = inet_addr(ipAddress.c_str());
   servaddr.sin_port = htons(atoi(argv[2]));		//convert port to an int and set as port


//SENDING CLIENT INFO TO SERVER----------------------------------------------
   //connect to the server
   if (connect(sock, (struct sockaddr *)&servaddr, sizeof(servaddr)) < 0)
   {
	  cout << "Error: failure connecting to server" << endl;
	  exit(1); 
   }
   
   self_ip_address = get_ip_address();
   //get ip address and send it
   char* ip_address = get_ip_address();
   short ip_addrlen = strlen(ip_address);
   ip_addrlen = htons(ip_addrlen);
   
   //send a "0" telling new connection
   short request_type = 0;
   request_type=htons(request_type);	
   if (sendto(sock,&request_type,sizeof(short),0,(struct sockaddr*)&servaddr,sizeof(servaddr)) < 0)
   {
	  printf("Error: sendto failure -> Request type for new connection to server\n");
   }
   
   //send ip address length
   if (sendto(sock,&ip_addrlen,sizeof(short),0,(struct sockaddr*)&servaddr,sizeof(servaddr)) < 0)
   {
	  printf("Error: sendto failure -> IP address length\n");
   }
   //send ip address
   if (sendto(sock,ip_address,strlen(ip_address),0,(struct sockaddr*)&servaddr,sizeof(servaddr)) < 0)
   {
	  printf("Error: sendto failure -> IP address value\n");
   }
//---------------------------------------------------------------------------

//SPAWN THREADS FOR CLIENT TO ACT AS SERVER TO OTHERS------------------------
	  pthread_t child_pid;
	  pthread_create(&child_pid, NULL, handle_connection, NULL);
//---------------------------------------------------------------------------

//LOOP FOR USER INPUT--------------------------------------------------------
   printWelcome();
   while(1)
   {
	  //print prompt
	  printf("input> ");
	  
	  //get the input
	  string input;
	  getline (cin, input);
	  
	  //parse it on the first space and test word
	  string first = findFirstWord(input);
	  
	  if (first == "search")	//perform a search
	  {
		 //send the request_type to the server
		 short request_type = 1;
		 request_type = htons(request_type);
		 if (sendto(sock,&request_type, sizeof(short),0,(struct sockaddr*)&servaddr,sizeof(servaddr)) < 0)
		 {
			printf("Error: sendto failure -> Request Type 1 (Search)\n");
		 }
		 
		 short num_clients;
		 //recieve response back from server of number of hosts
		 if (recv(sock,&num_clients,sizeof(short),0) < 0)
		 {
			cout << "Error: recv failure -> Num Clients" << endl;			   
		 }
		 //loop to receive info on all of the hosts
		 //empty the client list
		 client_list.clear();
		 for (int i=0; i<num_clients; i++)
		 {
			short ip_length;
			char ip_address[100];
			bzero(ip_address,100);
			//string ip;
			short port;
			if (recv(sock,&ip_length,sizeof(short),0) < 0)
			{
			   cout << "Error: recv failure -> Ip length" << endl;			   
			}
			//cout <<"ip_length: " << ip_length <<endl;
			if (recv(sock,&ip_address,ip_length,0) < 0)
			{
			   cout << "Error: recv failure -> Ip value" << endl;			   
			}
			//cout <<"ip_address: " << ip_address << endl;
			//cout <<"ip_address length: " << strlen(ip_address) << endl; 
			if (recv(sock,&port,sizeof(short),0) < 0)
			{
			   cout << "Error: recv failure -> Port" << endl;			   
			}
			
			string ip(ip_address);

			if (ip != self_ip_address)
			{
				client_info temp = make_pair(ip,port);
				client_list.push_back(temp);				
			}
		 }
		 
		 //print_client_list();
		 
		 //for each host query if they have the file
		 //second is the name of the file
		 string second = findSecondWord(input);

		for (unsigned int i=0; i<client_list.size(); i++)
   		{
   			check_for_file(second,client_list[i].first,client_list[i].second);
	  	}
	  }		
	  else if (first == "get") //get the file
	  {
		 string ip_address = findSecondWord(input);
		 string portString = findThirdWord(input);
		 int port = atoi(portString.c_str());
		 string file_name = findFourthWord(input);
		 get_file(file_name, ip_address, port);
	  }
	  else
	  {
		 cout << "Error on input" <<endl;
	  }
	  
   }

//---------------------------------------------------------------------------

   //close socket
   close (sock);
   return 0;
}

// background thread for handling requests from other clients
void* handle_connection(void* param){
	   // declare variables for networking stuff 
	   int sock;
	   int new_sock;
	   struct sockaddr_in servaddr,client_addr;
	   socklen_t len;
	   
	   //initialize values
	   bzero(&servaddr,sizeof(servaddr));
	   servaddr.sin_family = AF_INET;
	   servaddr.sin_addr.s_addr=htonl(INADDR_ANY);
	   servaddr.sin_port=htons(PORT);
	   
	   // set up passive open
	   if (( sock = socket(PF_INET, SOCK_STREAM, 0)) < 0)
	   {
		  perror ("Socket Error");
		  exit(1);
	   }
	   // bind and check for errors
	   if ((bind(sock, (struct sockaddr *)&servaddr, sizeof(servaddr))) < 0 )
	   {
		  perror ("Bind Error");
		  exit(1);
	   }
	   //listen
	   if (listen (sock, 1024) < 0)
	   {
		  cout << "Error on list" << endl;
	   }
		//loop for input 
	   while (1)
	   {
	   	  len = sizeof(client_addr);
		  if ((new_sock = accept(sock, (struct sockaddr *)&servaddr, &len)) < 0)
		  {
			 perror ("Accept Error");
			 exit(1);
		  }

		  //spawn a new thread to handle this connection
		  int *param = (int *) malloc (sizeof(*param));
		  *param = new_sock;
		  // create a new thread for the requests
		  pthread_t child_pid;
		  pthread_create(&child_pid, NULL, handle_request, param);
	   }
	   close (sock);
	   close (new_sock);
	   pthread_exit(NULL);
	return 0;
}


void* handle_request(void* param){
   // store socket information for thread connection locally
   int *fdptr = (int *) param;
   int client_local = *fdptr; 
   free (fdptr);
   
   socklen_t len;
   struct sockaddr_in client_addr;
   //struct sockaddr_in servaddr;
   //if (read(client_local,(struct client_data*)&data1,sizeof(data1))<0)
  len = sizeof(client_addr);
   
	  // determine the request type from the other client
	  // 1 is a search request
	  // 2 is a get request
	  short request_type;
	  if (recvfrom(client_local,&request_type,sizeof(short),0,(struct sockaddr *)&client_addr,&len)<0){
	  	cout << "Error receiving request type" << endl;
	  }
	  request_type=ntohs(request_type);
	  // handle a search request
	  if (request_type==1)
	  {
		//get file name
		short file_length;
		char file_name[100];
		if (recvfrom(client_local,&file_length,sizeof(short),0,(struct sockaddr *)&client_addr,&len) < 0)
		{
			cout << "Error: Search: recvfrom for file_length" << endl;
		}
		file_length = ntohs(file_length);
		if (recvfrom(client_local,&file_name,file_length,0,(struct sockaddr *)&client_addr,&len) < 0)
		{
			cout << "Error: Search: recvfrom for file_name" << endl;
		}
		//search for file return 0 for false, 1 for true, 2 for contains '*'
		//cout << "Searching for filelength: " << file_name << endl;
		short found=0;
		string temp1(file_name);
		vector<string> wildcard_matches;
		if (temp1.find('*') != std::string::npos) {
    		wildcard_matches = find_wildcard_matches(temp1);
    		found = 2;
		}else{
			vector<char *> client_data = searchDirectory();
			for (unsigned int i = 0; i < client_data.size(); i++)
			{
				string temp2(client_data[i]);
				if (temp1==temp2)
				{
					found=1;
				}
			}
		}
		if (found==2){
			found = htons(found);
			//send value for found back
			if (sendto(client_local,&found,sizeof(short),0,(struct sockaddr*)&client_addr,sizeof(client_addr)) < 0)
			{
			       printf("Error: Search: sendto failure -> File name for new connection to server\n");
			}
			// send the number of wildcard matches back
			short num_matches=wildcard_matches.size();
			num_matches = htons(num_matches);
			if (sendto(client_local,&num_matches,sizeof(short),0,(struct sockaddr*)&client_addr,sizeof(client_addr)) < 0)
			{
			       printf("Error: Search: sendto failure -> Number of wildcard matches\n");
			}
			// send he information for all of the wild card matches
			for (unsigned int i=0; i<wildcard_matches.size(); i++){
				//short name_size;
				//=wildcard_matches[i].size();
				//cout << name_size << endl;
				//name_size = htons(name_size);
				//// send the length of the filename
				//if (sendto(client_local,&name_size,sizeof(short),0,(struct sockaddr*)&client_addr,sizeof(client_addr)) < 0)
				//{
				//       printf("Error: Search: sendto failure -> Number of wildcard matches\n");
				//}
				//
				char file[100];
				bzero(file,100);
				strcpy(file,wildcard_matches[i].c_str());
				//cout << file << endl;
				// send the filename
				if (sendto(client_local,&file,100,0,(struct sockaddr*)&client_addr,sizeof(client_addr)) < 0)
				{
				       printf("Error: Search: sendto failure -> Wildcard filename\n");
				}
				
			}
		}else{ // no matches were found
			found = htons(found);
			//send value for found back
			if (sendto(client_local,&found,sizeof(short),0,(struct sockaddr*)&client_addr,sizeof(client_addr)) < 0)
			{
			       printf("Error: Search: sendto failure -> File name for new connection to server\n");
			}
		}	
	  }
	  //handle a get request
	  else if (request_type == 2)
	  {
		//get file name
		short file_length;
		char fileName[100];
		if (recvfrom(client_local,&file_length,sizeof(short),0,(struct sockaddr *)&client_addr,&len) < 0)
		{
			cout << "Error: Search: recvfrom for file_length" << endl;
		}
		file_length = ntohs(file_length);
		if (recvfrom(client_local,&fileName,file_length,0,(struct sockaddr *)&client_addr,&len) < 0)
		{
			cout << "Error: Search: recvfrom for file_name" << endl;
		}
	  
	  
	  //get fileSize and send it
		 int fileSize;
		int hostFileSize=0;
		char file_path[100];
		strcat(file_path,"./files/");
		strcat(file_path,fileName);
		//cout << file_path << endl;
		FILE *fp = fopen(file_path,"r");
		if(fp == NULL)
		{
			//printf("File could not be opened\n");
		}
		else
		{
			fseek(fp,0,SEEK_END); //find last byte of file
			fileSize = ftell(fp); //find size of file
			//convert to host size
			hostFileSize = ntohl(fileSize);
			rewind(fp); //return to beginning of file
			fclose(fp);
		}

		//send file size	
		send(client_local,&hostFileSize,sizeof(hostFileSize),0); 
	
	  if (hostFileSize > 0)
	  {
		 		//send the file
		//open a file to read the file to
		FILE *fp2 = fopen(file_path,"r");
					
		char *buffer;
		int res;
		buffer = (char*) malloc(sizeof(char)*fileSize);
		memset(&buffer[0],0,sizeof(buffer));
		res=fread(buffer,1,fileSize,fp2);
		if (res != fileSize)
		{
			printf("Error Reading the file to send\n");
		}
		fclose(fp2);
		
		int ret=0;
		int bytes=0;
		while (bytes < fileSize)
		{
			ret=send(client_local,buffer+bytes,fileSize-bytes,0);
			if (ret == -1)
			{
				break;
			}
			bytes+=ret;
		}
		
		free(buffer);
		//close(new_s);
	  }

	  
	  }
	  else
	  {
		 cout << "Invalid request" << endl;
	  }

	
	//cleanup
	//close(client_local); // close the socket for this thread
	//pthread_exit(NULL); // exit this thread
	return 0;
}


//Helper Functions
//check if this file exists at given ip/port and prints result
int check_for_file(string filename, string ip_address, int port){
	int client_sock;
   //initialize variables
   struct sockaddr_in servaddr;
   
   //create socket
   client_sock = socket(AF_INET, SOCK_STREAM, 0);
   if (client_sock < 0)
   {
	  cout << "Error: Failure creating socket" << endl;
	  exit(1);
   }
   
   //initialize server info
   bzero(&servaddr,sizeof(servaddr));
   servaddr.sin_family = AF_INET;
   servaddr.sin_addr.s_addr = inet_addr(ip_address.c_str());
   servaddr.sin_port = htons(port);		//convert port to an int and set as port

   //connect to the server
   if (connect(client_sock, (struct sockaddr *)&servaddr, sizeof(servaddr)) < 0)
   {
	  cout << "Error: failure connecting to client: " << ip_address << " at port: "<< port << endl;
	  //exit(1); 
   }
   else
   {
	  
   //send a search request
   short request_type = 1; //search
   request_type = htons(request_type);
   short file_length = strlen(filename.c_str());
   file_length = htons(file_length);
	char file_name[100];
	strcpy(file_name,filename.c_str());
    if (sendto(client_sock,&request_type,sizeof(short),0,(struct sockaddr*)&servaddr,sizeof(servaddr)) < 0)
   {
	  printf("Error: Search: sendto failure -> Request type for new connection to other client\n");
   }
    if (sendto(client_sock,&file_length,sizeof(short),0,(struct sockaddr*)&servaddr,sizeof(servaddr)) < 0)
   {
	  printf("Error: Search: sendto failure -> File length for new connection to other client\n");
   }
    if (sendto(client_sock,&file_name,file_length,0,(struct sockaddr*)&servaddr,sizeof(servaddr)) < 0)
   {
	  printf("Error: Search: sendto failure -> File name for new connection to server\n");
   }
	short found;
	if (recv(client_sock,&found,sizeof(short),0) < 0)
	{
		cout << "Error: Search: recvfrom for file_length" << endl;
	}
	found = ntohs(found);
	if (found == 1)
	{
		cout << "Querying ip address: " << ip_address << " port: " << port << " ---> Yes, has file " << filename<< endl;
	}
	else if (found == 0)
	{
		cout << "Querying ip address: " << ip_address << " port: " << port << " ---> No, does not have file " << filename<< endl;
	}
	else if (found == 2)
	{
		short num_matches;
		recv(client_sock,&num_matches,sizeof(short),0);
		num_matches = ntohs(num_matches);
		if (num_matches!=0){
			char file_name[100];
			for (int i=0; i<num_matches; i++){
				
                 socklen_t len;
				 len = sizeof(servaddr);		 
				 bzero(file_name,100);
				 // get File name
				 if (recvfrom(client_sock,&file_name,100,0,(struct sockaddr*)&servaddr,&len) < 0)
				 {
					cout << "Error: recv failure -> File Name" << endl;			   
				 }
				 
				cout << "Querying ip address: " << ip_address << " port: " << port << " ---> Yes, has file " << file_name << endl;
			}
		}else{
			cout << "Querying ip address: " << ip_address << " port: " << port << " ---> No, does not have file " << endl;
		}
	}
	else
	{
		cout << "SEARCHING ERROR" << endl;
	}
   close(client_sock);
   }

   return 0;
}

void get_file(string filename, string ip_address, int port)
{
   int client_sock;
   //initialize variables
   struct sockaddr_in servaddr;
   
   //create socket
   client_sock = socket(AF_INET, SOCK_STREAM, 0);
   if (client_sock < 0)
   {
	  cout << "Error: Failure creating socket" << endl;
	  exit(1);
   }
   
   //initialize server info
   bzero(&servaddr,sizeof(servaddr));
   servaddr.sin_family = AF_INET;
   servaddr.sin_addr.s_addr = inet_addr(ip_address.c_str());
   servaddr.sin_port = htons(port);		//convert port to an int and set as port  9979

   //connect to the server
   if (connect(client_sock, (struct sockaddr *)&servaddr, sizeof(servaddr)) < 0)
   {
	  cout << "Error: failure connecting to client: " << ip_address << " at port: "<< port << endl;
	  //exit(1); 
   }
   else
   {
	  //send a get request
   short request_type = 2; //get
   request_type = htons(request_type);
   short file_length = strlen(filename.c_str());
   file_length = htons(file_length);
	char file_name[100];
	strcpy(file_name,filename.c_str());
	
	//send request and file info
    if (sendto(client_sock,&request_type,sizeof(short),0,(struct sockaddr*)&servaddr,sizeof(servaddr)) < 0)
   {
	  printf("Error: Search: sendto failure -> Request type for new connection to other client\n");
   }
    if (sendto(client_sock,&file_length,sizeof(short),0,(struct sockaddr*)&servaddr,sizeof(servaddr)) < 0)
   {
	  printf("Error: Search: sendto failure -> File length for new connection to other client\n");
   }
    if (sendto(client_sock,&file_name,file_length,0,(struct sockaddr*)&servaddr,sizeof(servaddr)) < 0)
   {
	  printf("Error: Search: sendto failure -> File name for new connection to server\n");
   }
   
   //recieve file size and file
   	//receive the file length
	int fileSize=0;
	recv(client_sock, &fileSize,sizeof(fileSize),0);
	fileSize=ntohl(fileSize);
	


	//if file size is zero file doesnt exist
	if (fileSize == 0)
	{
		printf("File does not exist silly\n");
	}
	else
	{
	  	//open a file to read the file to
	char file_path[100];
	strcat(file_path,"./downloads/");
	strcat(file_path,filename.c_str());
    FILE *fp = fopen(file_path,"w");
		
	//receive file from server
	char buffer[4096];
	memset(&buffer[0],0,sizeof(buffer));
	int bytesTrans=0;
	int n;
	while ( bytesTrans < fileSize  )
	{
		n=read(client_sock, buffer, sizeof(buffer));
		bytesTrans+=n;
		fwrite(buffer,sizeof(char),n,fp);
		memset(&buffer[0],0,sizeof(buffer));
	}
	//close file
	fclose(fp);
	   cout <<"File transfer of " << filename <<" successful" << endl;

   }
   
	close(client_sock);
	}

}

vector<string> find_wildcard_matches(string filename){
	vector<char *> client_data = searchDirectory();
	vector<string> wild_card_matches;
	size_t wildcard_location = filename.find("*");
	string before = filename.substr(0, wildcard_location);;
	string after = filename.substr(wildcard_location+1, filename.length());;
	for (unsigned int i = 0; i < client_data.size(); i++)
	{
		string current_file(client_data[i]);
		// wildcard is the first character in the filename
		if (wildcard_location==0){
			if (current_file.compare(current_file.size()-after.size(),after.size(),after)==0){
				wild_card_matches.push_back(current_file);
			}
		}
		// wildcard is the last character in the filename
		else if (wildcard_location==filename.length()-1){
			if (current_file.compare(0,before.size(),before)==0){
				wild_card_matches.push_back(current_file);
			}
		}
		// wildcard is somewhere in the middle of the filename
		else{
			if ((current_file.compare(0,before.size(),before)==0) && (current_file.compare(current_file.size()-after.size(),after.size(),after)==0)){
				wild_card_matches.push_back(current_file);
			}
		}

	}
	return wild_card_matches;
}


//Get the ip address
char *get_ip_address(void)
{
   struct ifaddrs *ifap, *ifa;
   struct sockaddr_in *sa;
   char *addr;
   getifaddrs (&ifap);
   for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
       if (ifa->ifa_addr->sa_family==AF_INET) {
            sa = (struct sockaddr_in *) ifa->ifa_addr;
            addr = inet_ntoa(sa->sin_addr);
            if (strcmp(ifa->ifa_name,"eth0")==0){
    			freeifaddrs(ifap);
               	return addr;
            }
        }
    }
	return addr;
}

//return the first word in a string
string findFirstWord(string word)
{
   size_t found = word.find(" ");
   return word.substr(0, found);
}

//return the second word in a string
string findSecondWord(string word)
{
   size_t found = word.find(" ");
   string temp = word.substr(found+1, word.length());
   //first word removed
   found = temp.find(" ");
   temp = temp.substr(0,found);
   //3rd and 4th word removed
   return temp;
}
string findThirdWord(string word)
{
   size_t found = word.find(" ");
   string temp = word.substr(found+1, word.length());
   //first word removed
   found = temp.find(" ");
   temp = temp.substr(found+1, temp.length());
   //second word removed
   found = temp.find(" ");
   temp = temp.substr(0,found);
   //fourth word removed
   return temp;
}

string findFourthWord(string word)
{
   size_t found = word.find(" ");
   string temp = word.substr(found+1, word.length());
   //first word removed
   found = temp.find(" ");
   temp = temp.substr(found+1, temp.length());
   //second word removed
   found = temp.find(" ");
   temp = temp.substr(found+1, temp.length());
   //third word removed
   return temp;
}



//convert the hostname to an ipaddress
string hostname_to_ip(char * hostname)
{
    char ipAddress[100];
	struct hostent *he;
	struct in_addr **addr_list;
	int i;

	if ( (he = gethostbyname( hostname ) ) == NULL) 
	{
		// get the host info
		cout <<"Error converting hostname to Ip Address" << endl;
		exit(1);
	}

	addr_list = (struct in_addr **) he->h_addr_list;

	for(i = 0; addr_list[i] != NULL; i++) 
	{
		//Return ip address
		strcpy(ipAddress , inet_ntoa(*addr_list[i]) );
	}
	string temp(ipAddress);
	return temp;
}

//check to ensure user passed correct number of arguments and print error otherwise
void checkInput(int argc)
{
   
   if (argc != 3)
   {
	  printf("Error: Incorrect input!\n");
	  printf("usage:./client IP address Port #\n");
	  exit(1);
   }
}

vector<char *> searchDirectory(void)
{
   DIR *dp;
   struct dirent *ep;
   vector<char *> Client_data;
   
   //------------------------------------------//
   //dirent structure includes:				//
   //	ino_t	d_ino		file serial number	//
   // 	char 	d_name[]	name of entry		//
   //------------------------------------------//
   
   //open the directory stream
   dp = opendir ("./files");
   
   //if directory stream was opened successfully
   if (dp != NULL)
   {
	  //readdir function reads the next entry from the directory
	  while ((ep = readdir (dp)))
	  {
		 //only add the file to directory if doesn't start with '.'
		 if (ep->d_name[0]!='.')
		 {
			Client_data.push_back(ep->d_name);			
		 }
	  }
	  
	  //Print Client_data vector to console
	  //copy(Client_data.begin(), Client_data.end(), ostream_iterator<string>(cout, " "));
   }
   else
   {
	  printf("Error: Could not open the directory\n");
   }
   return Client_data;
}

void print_client_list(void)
{
  cout << endl << "printing client list.. size:" << client_list.size() << endl;
   for (unsigned int i=0; i<client_list.size(); i++)
   {
	  cout << "IP Address:" << client_list[i].first << " Port:" << client_list[i].second << endl;
   }
}

void printWelcome(void)
{
   cout << "Welcome to P2P File sharer." << endl;
   cout << "Syntax is as follows:" << endl;
   cout << "\tTo search for a file:" << endl;
   cout << "\t\tsearch <filename>" << endl;
   cout << "\tTo retrieve a file:" << endl;
   cout << "\t\tget <ip address> <port> <filename>" <<endl;
}
